#include "TcpSession.h"
#include <boost/bind.hpp>

TcpSession::TcpSession(boost::asio::io_service& io_service) : socket_(io_service), m_Sending ( false )
{
}

tcp::socket& TcpSession::socket()
{
	return socket_;
}

void TcpSession::startRead ( )
{
	boost::asio::async_read_until(socket_, m_ReadBuffer, "\r\n",boost::bind(&TcpSession::handle_read, shared_from_this(),
		  boost::asio::placeholders::error,
		  boost::asio::placeholders::bytes_transferred));
}

void TcpSession::start()
{
	startRead();
}

void TcpSession::handle_read(const boost::system::error_code& error, size_t bytes_received)
{
	if (!error)
	{
      std::istream response_stream(&m_ReadBuffer);
      std::string header;
      while (std::getline(response_stream, header) && header != "\r")
	  {
		if ( !dataReceived(header.c_str(), header.length()) )
		{
			return; // this will close our socket since we don't call startRead anymore and the shared_from_this ptr goes out of scope.
		}
	  }
	  startRead();
	}
	else
	{
	  // delete this;
	}
}

void TcpSession::handle_write(const boost::system::error_code& error)
{
	m_Sending = false;

	if (!error)
	{	
		processOutgoing();
	}
	else
	{
		OutputDebugString("Whoops");
	  // delete this;
	}
}

void TcpSession::processOutgoing()
{
	{
		boost::unique_lock<boost::mutex> lock(m_Mutex);
		
		if ( m_Sending )
			return;

		if ( m_Outgoing.size() > 0 ) 
		{
			m_OutgoingBuffer = m_Outgoing.front();
			m_Outgoing.pop_front();
			m_Sending = true;
		}
		else
		{
			return;
		}
	}

	boost::asio::async_write(socket_,
	  boost::asio::buffer(m_OutgoingBuffer.c_str(), m_OutgoingBuffer.length()),
	  boost::bind(&TcpSession::handle_write, shared_from_this(),
		boost::asio::placeholders::error));
}

void TcpSession::send( const std::string & data )
{
	{
		boost::unique_lock<boost::mutex> lock(m_Mutex);
		m_Outgoing.push_back(data);
	}
	processOutgoing();
}
